﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;

namespace MadProps
{
    public class PropChangedEventArgs : EventArgs
    {
        public IProp Prop { get; private set; }
        public object OldValue { get; private set; }
        public object NewValue { get; private set; }

        public PropChangedEventArgs(IProp prop, object oldValue, object newValue)
        {
            this.Prop = prop.ThrowIfNull("prop");
            this.OldValue = oldValue;
            this.NewValue = newValue;
        }

        HashSet<object> visited = new HashSet<object>(ObjectReferenceEqualityComparerer<object>.Default);
        internal bool HasVisited(object o)
        {
            if (visited.Contains(o))
            {
                return true;
            }
            visited.Add(o);
            return false;
        }
    }

    // thanks http://stackoverflow.com/questions/1890058/iequalitycomparert-that-uses-referenceequals
    /// <summary>
    /// A generic object comparerer that would only use object's reference, 
    /// ignoring any <see cref="IEquatable{T}"/> or <see cref="object.Equals(object)"/>  overrides.
    /// </summary>
    class ObjectReferenceEqualityComparerer<T> : EqualityComparer<T>
        where T : class
    {
        private static IEqualityComparer<T> _defaultComparer;

        public new static IEqualityComparer<T> Default
        {
            get { return _defaultComparer ?? (_defaultComparer = new ObjectReferenceEqualityComparerer<T>()); }
        }

        public override bool Equals(T x, T y)
        {
            return object.ReferenceEquals(x, y);
        }

        public override int GetHashCode(T obj)
        {
            return RuntimeHelpers.GetHashCode(obj);
        }
    }
}
